// -*- mode: c++ -*-
%define DOCSTRING
"Python bindings for data analysis library"
%enddef

%module(docstring=DOCSTRING) dalib 

 %{
#define SWIG_FILE_WITH_INIT
#include "../pyframe.hpp"
#include "../netcdfWrite.hpp"
#include "../netcdfRead.hpp"
#include "../bandpassfilter.hpp"
#include "../fft.hpp"
#include "../vector_op.hpp"
#include "../eph_table.hpp"
 %}
 
%include stl.i
%include cpointer.i
// %include numpy.i

%init
%{
//    import_array();
%}

%typemap(out) gsl_complex_float {
    $result = PyComplex_FromDoubles(GSL_REAL($1),GSL_IMAG($1));
}

%typemap(out) gsl_complex  {
    $result = PyComplex_FromDoubles(GSL_REAL($1),GSL_IMAG($1));
}

class missing_data_error: public std::runtime_error {
};


class missing_frame_error: public std::runtime_error {
};


typedef struct
  {
    double dat[2];
  }
gsl_complex;

typedef struct
  {
    float dat[2];
  }
gsl_complex_float;

%exception {
    try {
        $action
    } catch (missing_data_error) {
        PyErr_SetString(PyExc_RuntimeError,"missing data");
        SWIG_fail;
    } catch (missing_frame_error) {
        PyErr_SetString(PyExc_RuntimeError,"missing frame");
        SWIG_fail;
    }
}

%feature("autodoc",
"Represents a vector of double precision complex numbers.
") cvector;
class cvector {
public:
%feature("autodoc","1") cvector;
%feature("docstring") "";
    cvector(unsigned int n);
%feature("autodoc","1") resize;
%feature("docstring") "";    
    void resize(unsigned int n);
%feature("autodoc","1") get;
%feature("docstring") "";    
    gsl_complex get(size_t i) const;
%feature("autodoc","1") set;
%feature("docstring") "";    
    void set(size_t i, double re, double im);
%feature("autodoc","1") size;
%feature("docstring") "";    
    size_t size() const;
};


%feature("autodoc",
"Represents a vector of double precision numbers.
") vector;
class vector {
public:
%feature("autodoc","1") vector;
%feature("docstring") 
"Costruttore. Viene creato un vettore di lunghezza n.";
    vector(unsigned int n);
%feature("autodoc","1") resize;
%feature("docstring") "La dimensione del vettore viene modificata a n";
    void resize(unsigned int n);
%feature("autodoc","1") get;
%feature("docstring") "Restituisce il valore dell'elementi i-esimo del vettore";
    double get(size_t i) const;
%feature("autodoc","1") set;
%feature("docstring") "Assegna all'elemento i-esimo del vettore il valore v";
    void set(size_t i, double v);
%feature("autodoc","1") size;
%feature("docstring") "Restituisce la dimensione attuale del vettore";
    size_t size() const;
    gsl_vector *v;
private:
};

%feature("autodoc",
"Represents a vector of single precision numbers.
") vectorf;
class vectorf {
public:
%feature("autodoc","1") vectorf;
%feature("docstring") "";
    vectorf(unsigned int n);
%feature("autodoc","1") resize;
%feature("docstring") "";
    void resize(unsigned int n);
%feature("autodoc","1") get;
%feature("docstring") "";
    float get(size_t i) const;
%feature("autodoc","1") set;
%feature("docstring") "";
    void set(size_t i, float v);
%feature("autodoc","1") size;
%feature("docstring") "";
    size_t size() const;
    gsl_vector_float *v;
private:
};

%feature("autodoc",
"Represents a vector of complex single precision numbers.
") cvectorf;
class cvectorf {
public:
%feature("autodoc","1") cvectorf;
%feature("docstring") "";
    cvectorf(unsigned int n);
%feature("autodoc","1") resize;
%feature("docstring") "";
    void resize(unsigned int n);
%feature("autodoc","1") get;
%feature("docstring") "";
    gsl_complex_float get(size_t i) const;
%feature("autodoc","1") set;
%feature("docstring") "";
    void set(size_t i, float re, float im);
%feature("autodoc","1") size;
%feature("docstring") "";
    size_t size() const;
    gsl_vector_complex_float *v;
private:
};

%feature("autodoc","1") getY;
%feature("docstring") "";
void getY(char *filename, char *channel, int gps, int len, vector *out);
%feature("autodoc","1") getY_missing;
%feature("docstring") "";
void getY_missing(char *filename, char *channel, int gps, int len, vector *out, vector *miss);
%feature("autodoc","1") getY_float;
%feature("docstring") "";
void getY_float(char *filename, char *channel, int gps, int len, vectorf *out);
%feature("autodoc","1") getY_missing_float;
%feature("docstring") "";
void getY_missing_float(char *filename, char *channel, int gps, int len, vectorf *out, vectorf *miss);
%feature("autodoc","1") getChannels;
%feature("docstring") "";
std::string getChannels(char *filename, int gps);


%feature("autodoc",
        "Output stream of double precision numbers") netcdf_os_double;
class netcdf_os_double {
public:
    %feature("autodoc","1") netcdf_os_double;
    %feature("docstring") "Constructor";
    netcdf_os_double(const char* filename, const char* channelname, int framesize=1024);
    %feature("autodoc","1") write;
    %feature("docstring") "Write data on the file";
    void write(vector* data);
    %feature("autodoc","1") set_rate;
    %feature("docstring") "Set the time sampling rate of the data stream";
    void set_rate(double dt);
    %feature("autodoc","1") set_checkpoint_size;
    %feature("docstring") "Set the number of frames in each file";
    void set_checkpoint_size(int numframes);
};

%feature("autodoc",
        "Output stream of complex single precision numbers.") netcdf_os_complex_float;
class netcdf_os_complex_float {
public:
    netcdf_os_complex_float(const char* filename, const char* channelname, int framesize=1024);
    void write(cvectorf* data);
    void write(vectorf* redata, vectorf* imdata);
    void set_rate(double dt);
    void set_checkpoint_size(int numframes);
};

%feature("autodoc",
        "Output stream of single precision numbers.") netcdf_os_float;
class netcdf_os_float {
public:
    netcdf_os_float(const char* filename, const char* channelname, int framesize=1024);
    void write(vectorf* data);
    void set_rate(double dt);
    void set_checkpoint_size(int numframes);
};

%feature("autodoc",
        "Input stream of complex single precision numbers.") netcdf_is_float;
class netcdf_is_complex_float {
public:
    netcdf_is_complex_float(const char* filename, const char* channelname);
    virtual ~netcdf_is_complex_float();
    void read(cvectorf* data);
    void read(vectorf* redata, vectorf* imdata);
    void read(cvectorf* data, vector* times);
    void read(vectorf* redata, vectorf* imdata, vector* times);
    void read(cvector* data);
    void read(vector* redata, vector* imdata);
    void read(cvector* data, vector* times);
    void read(vector* redata, vector* imdata, vector* times);
    
};


%feature("autodoc",
        "Band pass filter.") bandpassfilter;
class bandpassfilter {
public:    
  bandpassfilter(int N, double A, double fs, double fstop, double f0);
  virtual ~bandpassfilter();
  gsl_complex_float operator()(float x);
  void apply(cvectorf *out, vectorf *in);    
};

class real_fft {
public:
    real_fft(int size);
    void operator()(vector* in, cvector* out);
};


struct eph_table_entry {
    double t;
    double x,y,z;
    double vx,vy,vz;
};

class eph_table {
public:
  eph_table(const std::string& filename, double time_start, double time_end);
  virtual ~eph_table();
  void get(int i, eph_table_entry& interpolated);
  void get(eph_table_entry& interpolated);
};

void simple_stat(vectorf* v, vector* res);
void linear_combine(vector* a, vector* b, vector*c, double beta, double gamma);

void abs2(cvector* in, vector* out);
